#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
语音助手集成服务
整合语音转文本(ASR)和文本转回答(LLM)功能
"""

import json
import logging
import os
import time
from typing import Optional, Tuple
from asr_file_service import FileTranscriptionService
from text_to_response_websocket_service import TextToResponseWebSocketService
from simple_tts_service import SimpleTTSService

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class VoiceAssistant:
    """语音助手集成服务"""
    
    def __init__(self, config_path: str = "config.json"):
        """初始化语音助手"""
        with open(config_path, 'r', encoding='utf-8') as f:
            self.config = json.load(f)
        
        # 初始化文本转回答服务（WebSocket版本）
        self.text_service = TextToResponseWebSocketService(config_path)
        
        # 初始化语音合成服务
        tts_config = self.config['text_to_speech']
        self.tts_service = SimpleTTSService(
            app_id=tts_config['app_id'],
            api_key=tts_config['api_key'],
            api_secret=tts_config['api_secret']
        )
        
        logger.info("语音助手初始化完成")
    
    def process_audio_file(self, audio_file_path: str, stream: bool = False,
                          enable_web_search: bool = False) -> Tuple[str, str]:
        """
        处理音频文件，返回转写文本和AI回答
        
        Args:
            audio_file_path: 音频文件路径
            stream: 是否使用流式输出
            enable_web_search: 是否启用网络搜索
            
        Returns:
            Tuple[str, str]: (转写文本, AI回答)
        """
        logger.info(f"开始处理音频文件: {audio_file_path}")
        
        try:
            # 步骤1: 语音转文本
            logger.info("步骤1: 语音转文本...")
            asr_service = FileTranscriptionService(
                app_id=self.config['speech_to_text']['app_id'],
                access_key_id=self.config['speech_to_text']['access_key_id'],
                access_key_secret=self.config['speech_to_text']['access_key_secret'],
                audio_file_path=audio_file_path
            )
            
            transcribed_text = asr_service.get_transcribe_result()
            logger.info(f"转写结果: {transcribed_text}")
            
            if not transcribed_text.strip():
                return transcribed_text, "抱歉，没有识别到有效的语音内容。"
            
            # 步骤2: 文本转回答
            logger.info("步骤2: 文本转回答...")
            ai_response = self.text_service.get_response(
                text=transcribed_text,
                stream=stream,
                enable_web_search=enable_web_search
            )
            
            logger.info("语音助手处理完成")
            return transcribed_text, ai_response
            
        except Exception as e:
            error_msg = f"处理失败: {e}"
            logger.error(error_msg)
            return "", error_msg
    
    def process_text_directly(self, text: str, stream: bool = False,
                             enable_web_search: bool = False) -> str:
        """
        直接处理文本，获取AI回答
        
        Args:
            text: 输入文本
            stream: 是否使用流式输出
            enable_web_search: 是否启用网络搜索
            
        Returns:
            str: AI回答
        """
        return self.text_service.get_response(text, stream, enable_web_search)
    
    def synthesize_text_to_audio(self, text: str, output_file: str = None,
                                voice: str = "xiaoyan", speed: int = 50,
                                volume: int = 50, pitch: int = 50) -> bytes:
        """
        将文本合成为语音
        
        Args:
            text: 要合成的文本
            output_file: 输出音频文件路径（可选）
            voice: 发音人
            speed: 语速
            volume: 音量
            pitch: 音高
            
        Returns:
            bytes: 合成的音频数据
        """
        logger.info(f"开始语音合成: {text[:50]}...")
        
        try:
            audio_data = self.tts_service.synthesize(
                text=text,
                output_file=output_file,
                voice=voice,
                speed=speed,
                volume=volume,
                pitch=pitch
            )
            
            logger.info(f"语音合成完成，音频大小: {len(audio_data)} 字节")
            return audio_data
            
        except Exception as e:
            logger.error(f"语音合成失败: {e}")
            raise Exception(f"语音合成失败: {e}")
    
    def process_audio_to_audio(self, audio_file_path: str, output_file: str = None,
                              stream: bool = False, enable_web_search: bool = False,
                              voice: str = "xiaoyan", speed: int = 50,
                              volume: int = 50, pitch: int = 50) -> Tuple[str, str, bytes]:
        """
        完整的音频到音频流程：音频转文本 → 文本转回答 → 回答转语音
        
        Args:
            audio_file_path: 输入音频文件路径
            output_file: 输出音频文件路径（可选）
            stream: 是否使用流式输出
            enable_web_search: 是否启用网络搜索
            voice: 发音人
            speed: 语速
            volume: 音量
            pitch: 音高
            
        Returns:
            Tuple[str, str, bytes]: (转写文本, AI回答, 合成音频数据)
        """
        logger.info("开始完整的音频到音频流程")
        
        try:
            # 步骤1: 语音转文本
            transcribed_text, ai_response = self.process_audio_file(
                audio_file_path=audio_file_path,
                stream=stream,
                enable_web_search=enable_web_search
            )
            
            if not transcribed_text.strip():
                return transcribed_text, "抱歉，没有识别到有效的语音内容。", b""
            
            # 步骤2: 文本转语音
            audio_data = self.synthesize_text_to_audio(
                text=ai_response,
                output_file=output_file,
                voice=voice,
                speed=speed,
                volume=volume,
                pitch=pitch
            )
            
            logger.info("完整的音频到音频流程处理完成")
            return transcribed_text, ai_response, audio_data
            
        except Exception as e:
            logger.error(f"完整流程处理失败: {e}")
            return "", f"处理失败: {e}", b""
    
    def get_conversation_history(self):
        """获取对话历史"""
        return self.text_service.get_history()
    
    def clear_conversation_history(self):
        """清空对话历史"""
        self.text_service.clear_history()
    
    def process_text_input(self, text: str, stream: bool = False, 
                          enable_web_search: bool = False) -> str:
        """
        处理文本输入，获取AI回答
        
        Args:
            text: 输入文本
            stream: 是否使用流式输出
            enable_web_search: 是否启用网络搜索
            
        Returns:
            str: AI回答
        """
        return self.text_service.get_response(text, stream, enable_web_search)
    
    def synthesize_speech(self, text: str, output_file: str = None, 
                         voice: str = "xiaoyan", speed: int = 50, 
                         volume: int = 50, pitch: int = 50) -> bytes:
        """
        合成语音
        
        Args:
            text: 要合成的文本
            output_file: 输出文件路径（可选）
            voice: 发音人
            speed: 语速
            volume: 音量
            pitch: 音调
            
        Returns:
            bytes: 音频数据
        """
        return self.tts_service.synthesize(
            text=text,
            output_file=output_file,
            voice=voice,
            speed=speed,
            volume=volume,
            pitch=pitch
        )
    
    def get_audio_info(self, audio_file_path: str) -> dict:
        """
        获取音频文件信息
        
        Args:
            audio_file_path: 音频文件路径
            
        Returns:
            dict: 音频文件信息
        """
        if not os.path.exists(audio_file_path):
            return {"error": "文件不存在"}
        
        file_size = os.path.getsize(audio_file_path)
        # 假设PCM格式：16kHz, 16bit, 单声道
        estimated_duration = int(file_size / (16000 * 2) * 1000)  # 毫秒
        
        return {
            "file_path": audio_file_path,
            "file_size": file_size,
            "estimated_duration_ms": estimated_duration,
            "estimated_duration_sec": estimated_duration / 1000
        }


def main():
    """主函数 - 演示语音助手功能"""
    print("=== 语音助手集成服务演示 ===")
    print("1. 处理音频文件")
    print("2. 直接文本对话")
    print("3. 文本转语音合成")
    print("4. 完整音频到音频流程")
    print("5. 查看对话历史")
    print("6. 清空对话历史")
    print("7. 获取音频文件信息")
    print("0. 退出")
    
    # 创建语音助手实例
    assistant = VoiceAssistant()
    
    while True:
        try:
            choice = input("\n请选择功能 (0-7): ").strip()
            
            if choice == "0":
                print("退出程序")
                break
            elif choice == "1":
                # 处理音频文件
                audio_file = input("请输入音频文件路径 (默认: test_1.pcm): ").strip()
                if not audio_file:
                    audio_file = "test_1.pcm"
                
                if not os.path.exists(audio_file):
                    print(f"文件不存在: {audio_file}")
                    continue
                
                stream_mode = input("是否使用流式输出? (y/n, 默认n): ").strip().lower() == 'y'
                web_search = input("是否启用网络搜索? (y/n, 默认n): ").strip().lower() == 'y'
                
                print(f"\n处理音频文件: {audio_file}")
                print("=" * 50)
                
                try:
                    transcribed_text, ai_response = assistant.process_audio_file(
                        audio_file_path=audio_file,
                        stream=stream_mode,
                        enable_web_search=web_search
                    )
                    
                    print(f"\n【转写结果】")
                    print(f"用户: {transcribed_text}")
                    
                    print(f"\n【AI回答】")
                    if stream_mode:
                        print("助手: ", end="")
                        print(ai_response)
                    else:
                        print(f"助手: {ai_response}")
                        
                except Exception as e:
                    print(f"处理失败: {e}")
            
            elif choice == "2":
                # 直接文本对话
                text = input("请输入要询问的文本: ").strip()
                if not text:
                    print("文本不能为空")
                    continue
                
                stream_mode = input("是否使用流式输出? (y/n, 默认n): ").strip().lower() == 'y'
                web_search = input("是否启用网络搜索? (y/n, 默认n): ").strip().lower() == 'y'
                
                print(f"\n【文本对话】")
                print(f"用户: {text}")
                print("助手: ", end="")
                
                try:
                    response = assistant.process_text_directly(
                        text=text,
                        stream=stream_mode,
                        enable_web_search=web_search
                    )
                    if not stream_mode:
                        print(response)
                except Exception as e:
                    print(f"对话失败: {e}")
            
            elif choice == "3":
                # 文本转语音合成
                text = input("请输入要合成的文本: ").strip()
                if not text:
                    print("文本不能为空")
                    continue
                
                voice = input("请输入发音人 (默认: xiaoyan): ").strip() or "xiaoyan"
                speed = int(input("请输入语速 (0-100, 默认: 50): ").strip() or "50")
                volume = int(input("请输入音量 (0-100, 默认: 50): ").strip() or "50")
                pitch = int(input("请输入音高 (0-100, 默认: 50): ").strip() or "50")
                
                output_file = input("请输入输出音频文件路径 (可选): ").strip()
                if not output_file:
                    output_file = f"tts_output_{int(time.time())}.pcm"
                
                print(f"\n【文本转语音合成】")
                print(f"文本: {text}")
                print(f"发音人: {voice}")
                print(f"参数: 语速={speed}, 音量={volume}, 音高={pitch}")
                print("正在合成...")
                
                try:
                    audio_data = assistant.synthesize_text_to_audio(
                        text=text,
                        output_file=output_file,
                        voice=voice,
                        speed=speed,
                        volume=volume,
                        pitch=pitch
                    )
                    print(f"合成成功！音频大小: {len(audio_data)} 字节")
                    print(f"音频文件: {output_file}")
                except Exception as e:
                    print(f"合成失败: {e}")
            
            elif choice == "4":
                # 完整音频到音频流程
                audio_file = input("请输入音频文件路径 (默认: test_1.pcm): ").strip()
                if not audio_file:
                    audio_file = "test_1.pcm"
                
                if not os.path.exists(audio_file):
                    print(f"文件不存在: {audio_file}")
                    continue
                
                stream_mode = input("是否使用流式输出? (y/n, 默认n): ").strip().lower() == 'y'
                web_search = input("是否启用网络搜索? (y/n, 默认n): ").strip().lower() == 'y'
                
                voice = input("请输入发音人 (默认: xiaoyan): ").strip() or "xiaoyan"
                speed = int(input("请输入语速 (0-100, 默认: 50): ").strip() or "50")
                volume = int(input("请输入音量 (0-100, 默认: 50): ").strip() or "50")
                pitch = int(input("请输入音高 (0-100, 默认: 50): ").strip() or "50")
                
                output_file = input("请输入输出音频文件路径 (可选): ").strip()
                if not output_file:
                    output_file = f"full_audio_output_{int(time.time())}.pcm"
                
                print(f"\n【完整音频到音频流程】")
                print(f"输入音频: {audio_file}")
                print(f"输出音频: {output_file}")
                print("=" * 50)
                
                try:
                    transcribed_text, ai_response, audio_data = assistant.process_audio_to_audio(
                        audio_file_path=audio_file,
                        output_file=output_file,
                        stream=stream_mode,
                        enable_web_search=web_search,
                        voice=voice,
                        speed=speed,
                        volume=volume,
                        pitch=pitch
                    )
                    
                    print(f"\n【转写结果】")
                    print(f"用户: {transcribed_text}")
                    
                    print(f"\n【AI回答】")
                    if stream_mode:
                        print("助手: ", end="")
                        print(ai_response)
                    else:
                        print(f"助手: {ai_response}")
                    
                    print(f"\n【语音合成】")
                    print(f"合成成功！音频大小: {len(audio_data)} 字节")
                    print(f"音频文件: {output_file}")
                        
                except Exception as e:
                    print(f"处理失败: {e}")
            
            elif choice == "5":
                # 查看对话历史
                history = assistant.get_conversation_history()
                if not history:
                    print("暂无对话历史")
                else:
                    print("【对话历史】")
                    for i, msg in enumerate(history):
                        role = "用户" if msg["role"] == "user" else "助手"
                        content = msg["content"][:100] + "..." if len(msg["content"]) > 100 else msg["content"]
                        print(f"{i+1}. {role}: {content}")
            
            elif choice == "6":
                # 清空对话历史
                assistant.clear_conversation_history()
                print("对话历史已清空")
            
            elif choice == "7":
                # 获取音频文件信息
                audio_file = input("请输入音频文件路径: ").strip()
                if not audio_file:
                    continue
                
                info = assistant.get_audio_info(audio_file)
                if "error" in info:
                    print(f"错误: {info['error']}")
                else:
                    print("【音频文件信息】")
                    print(f"文件路径: {info['file_path']}")
                    print(f"文件大小: {info['file_size']} 字节")
                    print(f"预估时长: {info['estimated_duration_sec']:.2f} 秒")
            
            else:
                print("无效选择，请重新输入")
                
        except KeyboardInterrupt:
            print("\n\n程序被用户中断")
            break
        except Exception as e:
            print(f"发生错误: {e}")


if __name__ == "__main__":
    main()
